package com.geovis.emergency.spd.biz.pc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.geovis.common.auth.util.AuthUtil;
import com.geovis.common.core.api.Result;
import com.geovis.common.core.constant.CommonConstants;
import com.geovis.common.core.exception.BizException;
import com.geovis.emergency.spd.biz.pc.mapper.PcDrillDutyOrgMapper;
import com.geovis.emergency.spd.biz.pc.mapper.PcDrillDutyUserMapper;
import com.geovis.emergency.spd.biz.pc.mapper.PcDrillPlanDetailMapper;
import com.geovis.emergency.spd.biz.pc.mapper.PcDrillUserRoleMapper;
import com.geovis.emergency.spd.biz.pc.service.IPcDrillDutyOrgService;
import com.geovis.emergency.spd.biz.pc.service.IPcDrillUserRoleService;
import com.geovis.emergency.spd.biz.system.mapper.SystemRoleMapper;
import com.geovis.emergency.spd.biz.system.service.ISystemUserService;
import com.geovis.emergency.spd.biz.system.wrapper.ForestNodeMerger;
import com.geovis.emergency.spd.entity.pc.entity.PcDrillDutyOrg;
import com.geovis.emergency.spd.entity.pc.entity.PcDrillDutyUser;
import com.geovis.emergency.spd.entity.pc.entity.PcDrillPlanDetail;
import com.geovis.emergency.spd.entity.pc.entity.PcDrillUserRole;
import com.geovis.emergency.spd.entity.pc.pojo.enums.StatusEnum;
import com.geovis.emergency.spd.entity.pc.pojo.vo.PcDrillDutyOrgUserVO;
import com.geovis.emergency.spd.entity.pc.pojo.vo.PcDrillDutyOrgVO;
import com.geovis.emergency.spd.entity.pc.pojo.vo.PcDrillPlanDetailUsersVO;
import com.geovis.emergency.spd.entity.pc.pojo.vo.StringVO;
import com.geovis.emergency.spd.entity.system.constant.SystemRoleConstant;
import com.geovis.emergency.spd.entity.system.entity.SystemRole;
import com.geovis.emergency.spd.entity.system.entity.SystemUser;
import com.geovis.emergency.spd.entity.system.pojo.enums.RoleTypeEnum;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.hsqldb.lib.Collection;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 应急预案指挥模块 - 演练组织架构 服务实现类
 * </p>
 *
 * @author Lonsho
 * @since 2022-07-11
*/

@Service
@RequiredArgsConstructor
@Slf4j
public class PcDrillDutyOrgServiceImpl extends ServiceImpl<PcDrillDutyOrgMapper, PcDrillDutyOrg> implements IPcDrillDutyOrgService {
    private final PcDrillDutyUserMapper pcDutyUserMapper;
    private final PcDrillDutyOrgMapper pcDrillDutyOrgMapper;
    private final PcDrillPlanDetailMapper pcDrillPlanDetailMapper;
    private final SystemRoleMapper systemRoleMapper;
    private final IPcDrillUserRoleService pcDrillUserRoleService;
    private final ISystemUserService systemUserService;

    private List<String> getAllDutyOrgId(List<PcDrillDutyOrgVO> list){
        List<String> idList = Lists.newArrayList();
        for (PcDrillDutyOrgVO pcDrillDutyOrgVO : list) {
            idList.add(pcDrillDutyOrgVO.getId());
            if (CollUtil.isNotEmpty(pcDrillDutyOrgVO.getChildren())) {
                List<String> allDutyOrgId = getAllDutyOrgId(pcDrillDutyOrgVO.getChildren());
                idList.addAll(allDutyOrgId);
            }
        }
        return idList;
    }
    @Override
    public void removeDutyOrg(List<PcDrillDutyOrgVO> list,String pcDrillId){
        List<String> allDutyOrgId = getAllDutyOrgId(list);
        baseMapper.delete(
                Wrappers.lambdaQuery(PcDrillDutyOrg.class)
                        .eq(PcDrillDutyOrg::getPcDrillId,pcDrillId)
                        .notIn(PcDrillDutyOrg::getId,allDutyOrgId)
        );
        if (CollUtil.isNotEmpty(allDutyOrgId)){
            pcDutyUserMapper.delete(
                    Wrappers.lambdaQuery(PcDrillDutyUser.class)
                            .eq(PcDrillDutyUser::getPcDrillId,pcDrillId)
                            .notIn(PcDrillDutyUser::getPcDrillOrgId,allDutyOrgId)
            );
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveDrillDutyOrg(List<PcDrillDutyOrgVO> dutyOrgList, String drillId,String parentId,String ancestors) {
        for (PcDrillDutyOrgVO pcDrillDutyOrgVO : dutyOrgList) {
            pcDrillDutyOrgVO.setPcDrillId(drillId);
            String orgId = pcDrillDutyOrgVO.getId();
            if (StrUtil.isEmpty(parentId)){
                pcDrillDutyOrgVO.setParentId(CommonConstants.TREE_ROOT_CODE);
                pcDrillDutyOrgVO.setAncestors(CommonConstants.TREE_ROOT_CODE);
            }else {
                pcDrillDutyOrgVO.setParentId(parentId);
                pcDrillDutyOrgVO.setAncestors(ancestors);
            }
            if (StrUtil.isNotBlank(orgId)){
                PcDrillDutyOrg pcDrillDutyOrg = baseMapper.selectOne(
                        Wrappers.lambdaQuery(PcDrillDutyOrg.class)
                                .eq(PcDrillDutyOrg::getPcDrillId,drillId)
                                .eq(PcDrillDutyOrg::getId,orgId)
                                .last("limit 1")
                );
                if (ObjectUtil.isNotNull(pcDrillDutyOrg)){
                    BeanUtil.copyProperties(pcDrillDutyOrgVO,pcDrillDutyOrg);
                    baseMapper.updateById(pcDrillDutyOrg);
                    pcDrillDutyOrgVO.setId(pcDrillDutyOrg.getId());
                } else {
                    pcDrillDutyOrgVO.setId(null);
                    pcDrillDutyOrgVO.setCreateTime(null);
                    pcDrillDutyOrgVO.setUpdateTime(null);
                    pcDrillDutyOrgVO.setCreateBy(null);
                    pcDrillDutyOrgVO.setUpdateBy(null);
                    baseMapper.insert(pcDrillDutyOrgVO);
                }
            } else {
                pcDrillDutyOrgVO.setId(null);
                baseMapper.insert(pcDrillDutyOrgVO);
            }
            //保存人员
            saveDutyUser(pcDrillDutyOrgVO.getDutyOrgDeptList(),pcDrillDutyOrgVO,drillId);
            if (CollUtil.isNotEmpty(pcDrillDutyOrgVO.getChildren())){
                saveDrillDutyOrg(pcDrillDutyOrgVO.getChildren(),drillId,pcDrillDutyOrgVO.getId(),pcDrillDutyOrgVO.getAncestors()+","+pcDrillDutyOrgVO.getId());
            }
        }
    }
    public void saveDutyUser( List<PcDrillDutyOrgUserVO> dutyOrgUserList,PcDrillDutyOrgVO pcDrillDutyOrgVO,String drillId){
        //这里不能放下面的if里面，因为这里如果dutyOrgUserList为空，则表示用户想清除掉该org下选中的人
        pcDutyUserMapper.delete(
                Wrappers.lambdaQuery(PcDrillDutyUser.class)
                        .eq(PcDrillDutyUser::getPcDrillId,drillId)
                        .eq(PcDrillDutyUser::getPcDrillOrgId,pcDrillDutyOrgVO.getId()
        ));

        if (CollUtil.isNotEmpty(dutyOrgUserList)){
            SystemRole role=systemRoleMapper.selectById(pcDrillDutyOrgVO.getRoleIds());
            for (PcDrillDutyOrgUserVO pcDrillDutyOrgUserVO : dutyOrgUserList) {
                PcDrillDutyUser pcDrillDutyUser = BeanUtil.toBean(pcDrillDutyOrgUserVO, PcDrillDutyUser.class);
                pcDrillDutyUser.setPcDrillOrgId(pcDrillDutyOrgVO.getId());
                pcDrillDutyUser.setPcDrillId(drillId);
                pcDrillDutyUser.setDataStatus(StatusEnum.TRUE.getCode());
                pcDutyUserMapper.insert(pcDrillDutyUser);
                //todo 获取组织对应的角色,这里可以优化

                //设置演练与用户角色关系
                saveDrillUserRole(pcDrillDutyUser.getPrincipalIds(),drillId,pcDrillDutyOrgVO.getRoleIds(),role.getEnName());

            }
        }

    }

    private void saveDrillUserRole(String userIds,String drillId,String orgRoleId,String orgRoleName)
    {
        List<String> userList=Arrays.asList(userIds.split(","));

        //新逻辑：同一个人，在一个演练里面，可能在同一角色的不同小组被选中，如张山，可以在演练组1,和演练组2里面
        // 但不会同时存在2个不同角色的小组
        userList.stream().forEach(userId->{
            PcDrillUserRole drillUserRole=pcDrillUserRoleService.getOne( Wrappers.lambdaQuery(PcDrillUserRole.class)
                    .eq(PcDrillUserRole::getPcDrillId,drillId)
                    .eq(PcDrillUserRole::getUserId,userId));
            if(drillUserRole==null)
            {
                PcDrillUserRole ur=new PcDrillUserRole();
                ur.setPcDrillId(drillId)
                        .setUserId(userId)
                        .setRoleId(orgRoleId)
                        .setRoleName(orgRoleName);
                pcDrillUserRoleService.save(ur);
            }
            else
            {
                if(!orgRoleId.equals(drillUserRole.getRoleId()))
                {
                    String name=systemUserService.getById(userId).getRealName();

                    throw new BizException("同一个用户【"+name+"】不能在不同角色的组织机构！");
                }
            }

        });

    }
    public List<String> myDutyGroupList(String drillId,boolean showAll){
//        String userId="1520215084872249345";//导条组
//        String userId="1520215472983781378";//演练组
        String userId=AuthUtil.getCurrentUserId();
        List<PcDrillDutyUser> list = pcDutyUserMapper.selectList(
                Wrappers.lambdaQuery(PcDrillDutyUser.class)
                        .eq(PcDrillDutyUser::getPcDrillId, drillId)
                        .apply("{0} = ANY (string_to_array(principal_ids,','))",userId)
                        .select(PcDrillDutyUser::getPcDrillOrgId)
        );
        Set<String> orgIdList = list.stream().map(PcDrillDutyUser::getPcDrillOrgId).collect(Collectors.toSet());
        if (CollUtil.isNotEmpty(orgIdList)){
            List<PcDrillDutyOrg> dutyOrgList = baseMapper.selectList(
                    Wrappers.lambdaQuery(PcDrillDutyOrg.class)
                            .in(PcDrillDutyOrg::getId, orgIdList)
            );
            Set<String> allOrgIdList =  CollUtil.set(false);;
            for (PcDrillDutyOrg pcDrillDutyOrg : dutyOrgList) {
                if (StatusEnum.FALSE.getCode().equals(pcDrillDutyOrg.getParentId())){
                    allOrgIdList.add(pcDrillDutyOrg.getId());
                }else {
                    String[] split = pcDrillDutyOrg.getAncestors().split(",");
                    if (showAll){
                        if (split.length > 1){
//                            for(int i = 1;i < split.length;i++){
//                                allOrgIdList.add(split[i]);
//                            }
                            Set<String> orgIdSetList = baseMapper.selectList(
                                    Wrappers.lambdaQuery(PcDrillDutyOrg.class)
                                            .like(PcDrillDutyOrg::getAncestors,split[1])
                            ).stream().map(PcDrillDutyOrg::getId).collect(Collectors.toSet());
                            if (ObjectUtil.isNotEmpty(orgIdList)){
                                allOrgIdList.addAll(orgIdSetList);
                            }
                        }
                        allOrgIdList.add(pcDrillDutyOrg.getId());
                    }else {
                        if (split.length > 1){
                            allOrgIdList.add(split[1]);
                        }
                    }

                }
            }
            if (showAll){
                return Lists.newArrayList(allOrgIdList);
            }
            if (CollUtil.isNotEmpty(allOrgIdList)){
                return baseMapper.selectList(
                        Wrappers.lambdaQuery(PcDrillDutyOrg.class)
                                .select(PcDrillDutyOrg::getId)
                                .eq(PcDrillDutyOrg::getPcDrillId,drillId)
                                .in(PcDrillDutyOrg::getId, allOrgIdList)
                ).stream().map(PcDrillDutyOrg::getId).distinct().collect(Collectors.toList());
            }
        }
        return Lists.newArrayList();
    }

    @Override
    public String getUserGroupId4WorkPlan(String drillId) {
        String userId=AuthUtil.getCurrentUserId();
        PcDrillUserRole userRole=pcDrillUserRoleService.getOne(Wrappers.lambdaQuery(PcDrillUserRole.class)
                .eq(PcDrillUserRole::getPcDrillId,drillId)
                .eq(PcDrillUserRole::getUserId,userId));
        SystemRole role=systemRoleMapper.selectById(userRole.getRoleId());
        //如果是导调组或领导组的角色，则可以查看所有的工作方案，如果不是，则只能查看当前用户所在组的方案
        if(SystemRoleConstant.TYPE_PILOT.equals(role.getEnName()) || SystemRoleConstant.TYPE_LEADER.equals(role.getEnName()))
        {
            return null;
        }
        List<PcDrillDutyUser> users=pcDutyUserMapper.selectList(Wrappers.lambdaQuery(PcDrillDutyUser.class)
                .eq(PcDrillDutyUser::getPcDrillId,drillId)
                .like(PcDrillDutyUser::getPrincipalIds,userId));
        //目前的逻辑，一个用户在一个演练中，只会被分配到一个组织节点
        return users.get(0).getPcDrillOrgId();
    }

    @Override
    public List<PcDrillPlanDetailUsersVO> getUsers4WorkPlan(String drillId) {
        List<PcDrillDutyUser> drillDutyUser=getDrillDutyUser(drillId);
        if(CollectionUtils.isEmpty(drillDutyUser))
        {
            return Collections.emptyList();
        }
        //目前的逻辑，一个用户在一个演练中，只会被分配到一个组织节点
        PcDrillDutyUser user=drillDutyUser.get(0);
        String[] userIds=user.getPrincipalIds().split(",");
        String[] userNames=user.getPrincipalNames().split(",");
        List<PcDrillPlanDetailUsersVO> userVos=new ArrayList<>();
        for(int x=0;x<userIds.length;x++)
        {
            PcDrillPlanDetailUsersVO usersVO=new PcDrillPlanDetailUsersVO();
            usersVO.setPrincipalId(userIds[x]);
            usersVO.setPrincipalName(userNames[x]);
            userVos.add(usersVO);
        }
        return userVos;
    }

    private List<PcDrillDutyUser> getDrillDutyUser(String drillId)
    {
        String userId=AuthUtil.getCurrentUserId();
        return pcDutyUserMapper.selectList(Wrappers.lambdaQuery(PcDrillDutyUser.class)
                .eq(PcDrillDutyUser::getPcDrillId,drillId)
                .like(PcDrillDutyUser::getPrincipalIds,userId));
    }

    @Override
    public String getUserGroupId(String drillId) {
        List<PcDrillDutyUser> drillDutyUser=getDrillDutyUser(drillId);
        if(CollectionUtils.isEmpty(drillDutyUser))
        {
            throw new BizException("用户所属机构不存在");
        }
        return drillDutyUser.get(0).getPcDrillOrgId();
    }

    @Override
    public String getGroupDuty(String drillId, String groupId) {
        List<PcDrillDutyUser> users=pcDutyUserMapper.selectList(Wrappers.lambdaQuery(PcDrillDutyUser.class)
                .eq(PcDrillDutyUser::getPcDrillId,drillId)
                .eq(PcDrillDutyUser::getPcDrillOrgId,groupId));
        List<String> dutys=users.stream().map(PcDrillDutyUser::getDuty).collect(Collectors.toList());
        return String.join(";",dutys);
    }

    public List<PcDrillDutyOrgVO> getDrillDutyOrg(String pcDrillId,String pcPlanId,String orgId){
        //获取主事件的组织架构
        List<PcDrillDutyOrg> dutyOrgList =  baseMapper.selectList(
                Wrappers.lambdaQuery(PcDrillDutyOrg.class)
                        .eq(PcDrillDutyOrg::getPcDrillId, pcDrillId)
                        .eq(StrUtil.isNotBlank(pcPlanId),PcDrillDutyOrg::getPcPlanId,pcPlanId)
                        .eq(orgId!=null,PcDrillDutyOrg::getId,orgId)
                        .orderByDesc(PcDrillDutyOrg::getParentId)
                        .orderByAsc(PcDrillDutyOrg::getId)
        );
        if (CollUtil.isNotEmpty(dutyOrgList)){
            //勾选的组织架构成员单位
            List<PcDrillDutyUser> dutyOrgDeptList = pcDutyUserMapper.selectList(
                    Wrappers.lambdaQuery(PcDrillDutyUser.class)
                            .in(PcDrillDutyUser::getPcDrillOrgId,dutyOrgList.stream().map(PcDrillDutyOrg::getId).collect(Collectors.toList()))
                            .eq(PcDrillDutyUser::getPcDrillId, pcDrillId)

            );
            List<PcDrillDutyOrgVO> drillDutyOrgList = dutyOrgList.stream().map(dutyOrgVO -> {
                PcDrillDutyOrgVO pcDrillDutyOrgVO = BeanUtil.toBean(dutyOrgVO, PcDrillDutyOrgVO.class);
                List<PcDrillDutyOrgUserVO> dutyOrgUserList = dutyOrgDeptList.stream()
                        .filter(s -> dutyOrgVO.getId().equals(s.getPcDrillOrgId()))
                        .map(s -> BeanUtil.toBean(s, PcDrillDutyOrgUserVO.class))
                        .collect(Collectors.toList());
                pcDrillDutyOrgVO.setDutyOrgDeptList(dutyOrgUserList);

                return pcDrillDutyOrgVO;
            }).collect(Collectors.toList());
            return ForestNodeMerger.merge(drillDutyOrgList);
        }
        return null;
    }

    @Override
    public List<StringVO> dutyGroupList(String drillId) {
        //任务用户列表
        List<String> userTaskGroupList = pcDrillPlanDetailMapper.selectList(
                Wrappers.lambdaQuery(PcDrillPlanDetail.class)
                        .eq(PcDrillPlanDetail::getPcDrillId, drillId)
                        .select(PcDrillPlanDetail::getGroupId)
        ).stream().map(PcDrillPlanDetail::getGroupId).distinct().collect(Collectors.toList());

        if (ObjectUtil.isNotEmpty(userTaskGroupList)){
            List<PcDrillDutyOrg> list = pcDrillDutyOrgMapper.selectList(
                    Wrappers.<PcDrillDutyOrg>lambdaQuery()
//                            .eq(PcDrillDutyOrg::getParentId, StatusEnum.FALSE.getCode())//这里需要讨论
                            .eq(PcDrillDutyOrg::getPcDrillId, drillId)
                            //.likeLeft(PcDrillDutyOrg::getOrgName,"组")//这里需要讨论
                            .in(PcDrillDutyOrg::getId,userTaskGroupList)
                            .orderByAsc(PcDrillDutyOrg::getIdx)
            );
            return list.stream().map(
                    p -> StringVO.newEntity(p.getId(), p.getOrgName())
            ).collect(Collectors.toList());
        }else {
            return Lists.newArrayList();
        }
    }
}
